import  { Mesh, CircleGeometry, DoubleSide, Object3D, Sprite, SpriteMaterial, Vector3 } from "three";
import vjmap3d, { App, Entity, PathTubeEntities } from "vjmap3d";


/** 计算管道实体中所有的出口位置坐标 */
export const getEndPoints = (tubeEntity: PathTubeEntities) => {
    let points = []
    // 如果节点只有一条相关联的管道就是出口了
    let nodes = tubeEntity.topo.nodes;
    for (let [key, value] of nodes) {
        if (value.length == 1) {
            let tube = tubeEntity.topo.tubes[value[0]];
            if (tube.startNodeId == key) {
                // 如果是开始点
                points.push(tube.data.paths[0])
            } else  if (tube.endNodeId == key) {
                // 如果是开始点
                points.push(tube.data.paths[tube.data.paths.length - 1])
            }
        }
    }
    return points;
}


/** 用shader创建一个扩散效果 */
export const createShaderWave = (parent: Object3D, position: Vector3, app: App) => {
    // 下面代码来源于 shadertoy示例 https://www.shadertoy.com/view/ldlXRS
    let shader = `
    // Noise animation - Electric
    // by nimitz (stormoid.com) (twitter: @stormoid)
    // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
    // Contact the author for other licensing options

    //The domain is displaced by two fbm calls one for each axis.
    //Turbulent fbm (aka ridged) is used for better effect.

    #define time iTime*0.15
    #define tau 6.2831853


    float circ(vec2 p) 
    {
        float r = length(p);
        r = log(sqrt(r));
        return abs(mod(r*4.,tau)-3.14)*3.+.2;

    }

    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
        //setup system
        vec2 p = fragCoord.xy / iResolution.xy-0.5;
        p.x *= iResolution.x/iResolution.y;
        p*=4.;
        
        float rz = 1.;
        
        //rings
        p /= exp(mod(time*10.,3.14159));
        rz *= pow(abs((0.1-circ(p))),.9);
        
        //final color
        vec3 col = vec3(.2,0.1,0.4)/rz;
        col=pow(abs(col),vec3(.99));
        fragColor = vec4(col,1.);
    }
    `;
    let texture3d = new vjmap3d.ShadertoyMaterial(app, {
        shader: shader,
        brightOpacity: 1,
        hsbOffset: [0.2, 0, 0],
        // hsbExpr: `hsb.x += sin(iTime);`,
        // @ts-ignore
        transparent: true,
        //sizeAttenuation: false,
        side: DoubleSide
        //sizeAttScale: 0.5
    });

    let size = 3;
    let pos = position ?? new Vector3(0, 0, 0);
    let geom = new CircleGeometry(size);
    // @ts-ignore
    let mesh = new Mesh(geom, texture3d);
    mesh.position.copy(pos);
    parent.add(mesh);
    mesh.scale.set(1.0 / parent.scale.x, 1.0 / parent.scale.y, 1.0 / parent.scale.z);
    
    return mesh;
};

/** 创建一个动画点精灵 */
export const createWavePoint = (parent: Object3D, position: Vector3, app: App) => {
    let spriteMaterial = new SpriteMaterial({
        map: app.getLoadedResources().getTexture("wave"),
        transparent: true,
        color: 0x00ffff
    });
    let sprite = new Sprite(spriteMaterial);
    sprite.position.copy(position);
    parent.add(sprite);

    // 和创建的对象相关联，创建一个实体，用来做动画
    let spriteEntity = Entity.attchObject(sprite, false, false, app);
    let s = 0.0;
    let maxScale = 60;
    spriteEntity.addAction(() => {
        s += 0.01;
        if (s < 0.5) {
            sprite.scale.x = maxScale * (1 + s);
            sprite.scale.y = maxScale * (1 + s);
        } else if (s >= 0.5 && s < 1.0) {
            sprite.scale.x = maxScale * (2 - s);
            sprite.scale.y = maxScale * (2 - s);
        } else {
            s = 0.0;
        }
    });
    return {
        sprite,
        spriteEntity
    };
};
